/**
 * @(#)Text1.java
 *
 *
 * @author 
 * @version 1.00 2011/10/30
 */


public class register_map {
	public boolean registerUsed[];
	public int replacedBy[];
	public int replaces[];
	
    //Instance Constructor
    public register_map() {
    	registerUsed = new boolean[32];
    	replacedBy = new int[32];
    	replaces = new int[32];
    	for (int r = 0; r< 32;r++){
    		registerUsed[r] = false;
    		replacedBy[r] = -1;
    		replaces[r] = -1;
    	}
    }
    
    //Rename a register and return its 
    public String rename(String register){
    	int reg = reg_num(register);
    	int replacement = 0;
    	if(reg != -1 && reg != 29 
    		&& (register.substring(1).charAt(0) == 's' 
                || register.substring(1).charAt(0) == 't' 
    		|| register.substring(1).charAt(0) == 'S' 
                || register.substring(1).charAt(0) == 'T')){
    		
    		registerUsed[reg] = true;
    		//Replace register with a temporary register
	    	for (int r = 0; r < 10; r++){
	    		String temporary = new String("$t" + r);
	    		replacement  = reg_num(temporary);
	    		if (registerUsed[replacement] == false){
	    			registerUsed[replacement] = true;
	    			replacedBy[reg] = replacement;
	    			replaces[replacement] = reg;
	    			return temporary;
	    		}
	    	}
	    	//Replace register with a saved register
	    	/*
	    	for (int r = 0; r < 9; r++){
	    		String saved = new String("$s" + r);
	    		replacement  = reg_num(saved);
	    		if (registerUsed[replacement] == false){
	    			registerUsed[replacement] = true;
	    			replacedBy[reg] = replacement;
	    			replaces[replacement] = reg;
	    			return saved;
	    		}
	    	}
	    	*/	    	
    	}
    	//If no replacement was found, leave as is.
    	return register;
	}
    //Returns a replacement register if the register has been replaced. 
    //Otherwise, it returns the original argument
    public String alias(String register){
    	int reg = reg_num(register);
    	if (reg != -1){
	    	if (replacedBy[reg] != -1){
	    		int reg2 = replacedBy[reg];
               	//Handle $t0 ~ $t7
	    		if (reg2 >= 8 && reg2 <= 15) return "$t" + (reg2 - 8);		
                //Handle $t8 ~ $t9
	    		if (reg2 == 24 || reg2 == 25) return "$t" + (reg2 - 16);	
	    		//Handle $s0 ~$s7
	    		if (reg2 >=16 && reg2 <= 23) return "$s" + (reg2 - 16);	
				//Handle $s8
	    		if (reg2 == 30) return "$s8";							
	    		
	    		
	    		return new String("$" + reg);
	    	}
	    	else{
	    		return register;
	    	}
    	}
    	else return register;
    }
    
    public void setUsed(String register){
    	int reg = reg_num(register);
    		if (reg > -1) registerUsed[reg] = true;
    	
    }
    
    public boolean isUsed(String register){
    	int reg = reg_num(register);
    		if (reg > -1)
    			if(registerUsed[reg] == true)
    				return true;  
    	return false;  	
    }
    
    public void reset(){
    	for (int i = 0; i < 32; i++){
    		registerUsed[i] = false;
    		replacedBy[i] = -1;
    		replaces[i] = -1;
    	}
    }
    //Register Mapper
    public static int reg_num(String register){
    	String temp;
    	int rn = 0;
    	if (register.length() == 0) return -1;
    	if (register.charAt(0) == '$'){
                //Remove leading '$' from register string
    		temp = register.substring(1);					
                //parse a number after the leading s,t,a,k,v,
    		rn = parseNum(temp.substring(1));				
    		switch(temp.charAt(0)){
    			case 'S':
    			case 's':
                                //Handle $s0 through $s7
    				if (rn >=0 && rn <= 7) return rn + 16;		
    				//Handle $s8
                                if (rn == 8) return 30;    			
                                //Handle $sp
    				if (temp.equalsIgnoreCase("sp")) return 29;	
    				break;
    			case 'T':
    			case 't':
                                //Handle $t0 through $t7
                                if (rn >= 0 && rn <= 7 ) return rn + 8;		
                                //Handle $t8 through $t9
                                if (rn >= 8 && rn <= 9) return rn + 16;		
    				break;
    			case 'A':
    			case 'a':
                                //Handle $a0 through $a3
    				if (rn >=0 && rn <= 3)return rn + 4;		
    				//Handle $at
                                if (temp.equalsIgnoreCase("at")) return 1;	
    				break;
    			case 'K':
    			case 'k':
                                //Handle $k0 and $k1
    				if (rn >=0 && rn <= 1) return rn + 26;		
    				break;
    			case 'R':
    			case 'r':
                                //Handle $ra
    				if(temp.equalsIgnoreCase("ra"))return 31;	
    				break;
    			case 'V':
    			case 'v':
                                //Handle $v0 and $v1
    				if (rn >= 0 && rn <= 1) return rn + 2;		
    				break;
    			case 'Z':
    			case 'z':
                                //Handle $zero
    				if (temp.equalsIgnoreCase("zero")) return 0;
    				break;
    			case 'G':
    			case 'g':
                                //Handle $gp
    				if (temp.equalsIgnoreCase("gp")) return 28;	
    				break;	
    			default:
                                //If '$' was followed by a number, return the 
                                //register number.	
                                rn = parseNum(temp);						
    				if (rn > -1) return rn;
    				break;
    		}
    		return -1;
    	}
    	else{
    		return -1;
    	}
    }
    //Number Parser
    private static int parseNum(String value){
    	int data = 0;
    	int i = 0;
    	char c;
    	while (i < value.length()){
    		data *= 10;
    		c = value.charAt(i); 
    		if (c != '\0' && (c >='0' && c <= '9')){
    			data += c - '0';
    		}
    		else{
    			if (c != '\0') return -1;  		
    		}
    		i++;
    	}
    	return data;
    }
    
}